package com.hk.aspect;

import cn.hutool.json.JSONUtil;
import com.hk.annotation.RecordOperate;
import com.hk.domain.entity.OperateLogDo;
import com.hk.service.order.Convert;
import com.hk.service.order.impl.SaveOrderConvert;
import com.hk.service.order.impl.UpdateOrderConvert;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author: dpb
 * @Description TODO
 * @date: 2022/12/6 23:38
 * @Version 1.0
 */
@Aspect
@Component
@Slf4j
public class RecordOperateAspect {

    /**
     * 1、切入点
     * 2、横切逻辑
     * 3、织入
     */

    @Pointcut("@annotation(com.hk.annotation.RecordOperate)")
    public void pointcut() {}


    private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            1, 1, 1, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(100));

    @Around("pointcut()")
    public Object aroud(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = proceedingJoinPoint.proceed();

        threadPoolExecutor.execute(() -> {
            try {
                MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
                RecordOperate recordOperate = signature.getMethod().getAnnotation(RecordOperate.class);
                if (Objects.nonNull(recordOperate)) {

                    Class<? extends Convert> convert = recordOperate.convert();
                    Convert logConvert = convert.newInstance();
                    OperateLogDo operateLogDo = new OperateLogDo();

                    for (Object arg : proceedingJoinPoint.getArgs()) {
                        OperateLogDo covertLogDo = logConvert.covert(arg);
                        operateLogDo.setOrderId(covertLogDo.getOrderId());
                    }

                    String operateType = "";
                    if(logConvert instanceof SaveOrderConvert) {
                        operateType = "save operateLog~~";
                    } else if (logConvert instanceof UpdateOrderConvert) {
                        operateType = "update operateLog~~";
                    }
                    operateLogDo.setDesc(recordOperate.desc());
                    operateLogDo.setResult(result.toString());
                    log.info("{} , {}", operateType, JSONUtil.toJsonStr(operateLogDo));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return result;
    }


}
